#include <GL/glfw.h>
#include "Common/Algebra/Vec2.h"
#include "Drawing/Color.h"

#include "Window.h"
#include "GlDrawer.h"

using namespace std;
using namespace cmn;
using namespace drawing;

namespace core {

	Vec2 ConvertMousePos( int x, int y );
	int WindowModeToInt( WindowMode mode );

	Window::Window( const Point& position, const Size& size, const char* title, WindowMode mode ) :
		m_title( title ),
		m_position( position ),
		m_mode( mode )
	{
		glfwOpenWindowHint( GLFW_FSAA_SAMPLES, 4 );
		glfwOpenWindow( size.Width, size.Height, 8, 8, 8, 8, 8, 8, WindowModeToInt( m_mode ) );
		glfwSwapInterval( 0 );

		SetPosition( m_position );
		SetTitle( m_title );

		glfwDisable( GLFW_AUTO_POLL_EVENTS );
	}

	Window::~Window() {
		glfwCloseWindow();
		exit( EXIT_SUCCESS );
	}

	Point Window::GetPosition() const {
		return m_position;
	}

	void Window::SetPosition( const Point& pos ) {
		m_position = pos;
		glfwSetWindowPos( m_position.X, m_position.Y );
	}

	Size Window::GetSize() const {
		int width;
		int height;
		glfwGetWindowSize( &width, &height );
		return Size( width, height );
	}

	void Window::SetSize( const Size& size ) {
		glfwSetWindowSize( size.Width, size.Height );
	}

	const char* Window::GetTitle() const {
		return m_title;
	}

	void Window::SetTitle( const char* title ) {
		m_title = title;
		glfwSetWindowTitle( m_title );
	}

	WindowMode Window::GetMode() const {
		return m_mode;
	}

	void Window::SetMode( WindowMode mode ) {
		m_mode = mode;
		Size currentSize = GetSize();
		glfwCloseWindow();
		glfwOpenWindow( currentSize.Width, currentSize.Height, 8, 8, 8, 8, 8, 8, WindowModeToInt( m_mode ) );
	}

	bool Window::IsOpened() const {
		return glfwGetWindowParam( GLFW_OPENED ) == GL_TRUE;
	}

	bool Window::IsActive() const {
		return glfwGetWindowParam( GLFW_ACTIVE ) == GL_TRUE;
	}

	bool Window::IsIconified() const {
		return glfwGetWindowParam( GLFW_ICONIFIED ) == GL_TRUE;
	}

	void Window::PollEvents() {
		glfwPollEvents();
	}

	void Window::Draw() {
		Transform camera = GetCamera();

		glMatrixMode( GL_PROJECTION );
		glLoadIdentity();
		Size size = Window::GetSize();
		float aspect = float( size.Width ) / float( size.Height );
		glOrtho( -aspect, aspect, -1.0f, 1.0f, 1.0f, -1.0f );

		glMatrixMode( GL_MODELVIEW );
		glLoadIdentity();
		glScalef( camera.Scale, camera.Scale, camera.Scale );
		glRotatef( -ToDegrees( camera.Rot ), 0.0, 0.0, 1.0 );
		glTranslatef( -camera.Vec.X, -camera.Vec.Y, 0.0f );

        GlDrawer drawer( Color::Black() );

		DrawInner( drawer );

		glfwSwapBuffers();
	}

	void Window::Iconify() {
		glfwIconifyWindow();
	}

	void Window::Restore() {
		glfwRestoreWindow();
	}

	void Window::Resized( const Size& size ) {
		glViewport( 0, 0, size.Width, size.Height );
		ResizedInner( size );
	}

	void Window::Closed() {
		ClosedInner();
	}

	void Window::Refreshed() {
		RefreshedInner();
	}

	int WindowModeToInt( WindowMode mode ) {
		switch( mode ) {
			case WindowMode::Windowed:
				return GLFW_WINDOW;
			case WindowMode::Fullscreen:
				return GLFW_FULLSCREEN;
		}
		throw 0;
	}
}
